﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using System.Windows;
using System.Windows.Input;
using ToolRental.Client.Admin.AdminService;

namespace ToolRental.Client.Admin
{
    public class ViewModel : INotifyPropertyChanged
    {

        #region NewBorrowDeadline
        private DateTime newBorrowDeadline = DateTime.Now.AddDays(10);
        public DateTime NewBorrowDeadline
        {
            get
            {
                return newBorrowDeadline;
            }
            set
            {
                newBorrowDeadline = value;
                PropChanged("NewBorrowDeadline");
            }
        }
        #endregion

        #region NewBorrowSelectedTool
        private Model.Tool newBorrowSelectedTool;
        public Model.Tool NewBorrowSelectedTool
        {
            get
            {
                return newBorrowSelectedTool;
            }
            set
            {
                newBorrowSelectedTool = value;
                PropChanged("NewBorrowSelectedTool");
            }
        }
        #endregion

        #region NewBorrowTools
        private ObservableCollection<Model.Tool> newBorrowTools;
        public ObservableCollection<Model.Tool> NewBorrowTools
        {
            get
            {
                if (newBorrowTools == null)
                    newBorrowTools = new ObservableCollection<Model.Tool>();
                return newBorrowTools;
            }
            set
            {
                newBorrowTools = value;
                PropChanged("NewBorrowTools");
            }
        }
        #endregion

        #region BorrowedTools
        private ObservableCollection<Model.Borrow> borrowedTools;
        public ObservableCollection<Model.Borrow> BorrowedTools
        {
            get
            {
                if (borrowedTools == null)
                    borrowedTools = new ObservableCollection<Model.Borrow>();
                return borrowedTools;
            }
            set
            {
                borrowedTools = value;
                PropChanged("BorrowedTools");
            }
        }
        #endregion

        #region OrderedToolTypes
        private ObservableCollection<Model.Order> orderedToolTypes;
        public ObservableCollection<Model.Order> OrderedToolTypes
        {
            get
            {
                if (orderedToolTypes == null)
                    orderedToolTypes = new ObservableCollection<Model.Order>();
                return orderedToolTypes;
            }
            set
            {
                orderedToolTypes = value;
                PropChanged("OrderedToolTypes");
            }
        }
        #endregion

        #region NewToolTypeBrand
        private string newToolTypeBrand;
        public string NewToolTypeBrand
        {
            get
            {
                if (newToolTypeBrand == null)
                    newToolTypeBrand = "";
                return newToolTypeBrand;
            }
            set
            {
                newToolTypeBrand = value;
                PropChanged("NewToolTypeBrand");
            }
        }
        #endregion

        #region NewToolTypeName
        private string newToolTypeName;
        public string NewToolTypeName
        {
            get
            {
                if (newToolTypeName == null)
                    newToolTypeName = "";
                return newToolTypeName;
            }
            set
            {
                newToolTypeName = value;
                PropChanged("NewToolTypeName");
            }
        }
        #endregion

        #region NewToolStockNumber
        private string newToolStockNumber;
        public string NewToolStockNumber
        {
            get
            {
                if (newToolStockNumber == null)
                    newToolStockNumber = "";
                return newToolStockNumber;
            }
            set
            {
                newToolStockNumber = value;
                PropChanged("NewToolStockNumber");
            }
        }
        #endregion

        #region ToolTypes
        private ObservableCollection<ToolType> toolTypes;
        public ObservableCollection<ToolType> ToolTypes
        {
            get
            {
                return toolTypes;
            }
            set
            {
                toolTypes = value;
                PropChanged("ToolTypes");
            }
        }
        #endregion

        #region SelectedToolType
        private ToolType selectedToolType;
        public ToolType SelectedToolType
        {
            get
            {
                return selectedToolType;
            }
            set
            {
                selectedToolType = value;
                PropChanged("SelectedToolType");
            }
        }
        #endregion

        #region Tools
        private ObservableCollection<Tool> tools;
        public ObservableCollection<Tool> Tools
        {
            get
            {
                return tools;
            }
            set
            {
                tools = value;
                PropChanged("Tools");
            }
        }
        #endregion

        #region GetToolTypesCommand
        private ICommand getToolTypesCommand;
        public ICommand GetToolTypesCommand
        {
            get
            {
                if (getToolTypesCommand == null)
                    getToolTypesCommand = new CustomCommand(GetToolTypes);
                return getToolTypesCommand;
            }
        }

        public async void GetToolTypes()
        {
            StartOperation();
            try
            {
                ToolType[] toolTypes;
                using (var asc = new AdminServiceClient())
                {
                    toolTypes = await asc.GetToolTypesAsync();
                }
                var toolTypesCollection = new ObservableCollection<ToolType>();
                foreach (var tt in toolTypes)
                {
                    toolTypesCollection.Add(new ToolType()
                    {
                        BrandName = tt.BrandName,
                        Id = tt.Id,
                        TypeName = tt.TypeName
                    });
                }
                ToolTypes = toolTypesCollection;
            }
            catch (Exception e)
            {
                HostIsUnavailable(e.Message);
            }
            finally
            {
                FinishOperation();
            }
            
        }
        #endregion

        #region AddToolTypeCommand
        private ICommand addToolTypeCommand;
        public ICommand AddToolTypeCommand
        {
            get
            {
                if (addToolTypeCommand == null)
                    addToolTypeCommand = new CustomCommand(AddToolType);
                return addToolTypeCommand;
            }
        }
        public async void AddToolType()
        {
            if ((NewToolTypeBrand == "") || (NewToolTypeName == ""))
            {
                MessageBox.Show("Kérem adja meg a szükséges adatokat!");
            }
            else
            {
                try
                {
                    using (var asc = new AdminServiceClient())
                    {
                        await asc.AddToolTypeAsync(new ToolType()
                            {
                                BrandName = NewToolTypeBrand,
                                TypeName = NewToolTypeName
                            });
                    }
                    NewToolTypeName = "";
                    NewToolTypeBrand = "";
                }
                catch (Exception e)
                {
                    HostIsUnavailable(e.Message);
                }
                finally
                {
                    FinishOperation();
                }
            }
                
        }
        #endregion

        #region ToolTypeSelectionChangedCommand
        private ICommand toolTypeSelectionChangedCommand;
        public ICommand ToolTypeSelectionChangedCommand
        {
            get
            {
                if (toolTypeSelectionChangedCommand == null)
                    toolTypeSelectionChangedCommand = new CustomCommand(ToolTypeSelectionChanged);
                return toolTypeSelectionChangedCommand;
            }
        }
        public void ToolTypeSelectionChanged()
        {
            try
            {
                GetTools();
            }
            catch (Exception e)
            {
                HostIsUnavailable(e.Message);
            }
        }

        private async void GetTools()
        {
            Tool[] getTools;
            using (var asc = new AdminServiceClient())
            {
                getTools = await asc.GetToolsAsync(SelectedToolType.Id);
            }
            var toolCollection = new ObservableCollection<Tool>();
            foreach (var gt in getTools)
            {
                toolCollection.Add(new Tool()
                    {
                        StockNumber = gt.StockNumber,
                        Id = gt.Id,
                        ToolTypeId = gt.ToolTypeId,
                        ToolType = gt.ToolType
                    });
             }
            Tools = toolCollection;
        }
        #endregion

        #region AddNewToolCommand
        private ICommand addNewToolCommand;
        public ICommand AddNewToolCommand
        {
            get
            {
                if (addNewToolCommand == null)
                    addNewToolCommand = new CustomCommand(AddNewTool);
                return addNewToolCommand;
            }
        }

        public async void AddNewTool()
        {
            if ((NewToolStockNumber == "") && (SelectedToolType != null))
            {
                MessageBox.Show("Kérem adja meg a szügséges adatokat!");
            }
            else
            {
                try
                {
                    StartOperation();
                    using (var asc = new AdminServiceClient())
                    {
                        await asc.AddToolAsync(NewToolStockNumber, SelectedToolType.Id);
                        NewToolStockNumber = "";
                        GetTools();
                    }
                }
                catch (Exception e)
                {
                    HostIsUnavailable(e.Message);
                }
                finally
                {
                    FinishOperation();
                }
            }
        }
        #endregion

        #region StartBorrowCommand
        private ICommand startBorrowCommand;
        public ICommand StartBorrowCommand
        {
            get
            {
                if (startBorrowCommand == null)
                    startBorrowCommand = new CustomCommand(StartBorrow);
                return startBorrowCommand;
            }
        }

        public async void StartBorrow()
        {
            if ((NewBorrowSelectedTool != null) && (OrderedToolTypes != null))
            {
                var selectedOrder = OrderedToolTypes.Where(p => (p.IsChecked == true)).First();
                if ((NewBorrowSelectedTool.Id != 0) && (selectedOrder.Id != 0))
                {
                    try
                    {
                        using (var asc = new AdminServiceClient())
                        {
                            await asc.NewBorrowAsync(selectedOrder.Id, newBorrowSelectedTool.Id, NewBorrowDeadline);
                        }
                        RefreshBorrow();
                    }
                    catch (Exception e)
                    {
                        HostIsUnavailable(e.Message);
                    }
                }
            }
            else
            {
                MessageBox.Show("Kérem adja meg a szükséges adatokat!!");
            }

        }
        #endregion

        #region FinishBorrowCommand
        private ICommand finishBorrowCommand;
        public ICommand FinishBorrowCommand
        {
            get
            {
                if (finishBorrowCommand == null)
                    finishBorrowCommand = new CustomCommand(FinishBorrow);
                return finishBorrowCommand;
            }
        }

        private async void FinishBorrow()
        {
            var sBorrow = BorrowedTools.Where(p => p.IsChecked == true);

            if (sBorrow.Count() > 0)
            {
                var selectedBorrow = sBorrow.First();
                try
                {
                    using (var asc = new AdminServiceClient())
                    {
                        await asc.DeleteBorrowAsync(selectedBorrow.Id);
                    }
                    RefreshBorrow();
                }
                catch (Exception e)
                {
                    HostIsUnavailable(e.Message);
                }
            }
            else
            {
                MessageBox.Show("Kérem válasszon ki egy kölcsönzést!");
            }
        }

        #endregion

        #region RefreshBorrowCommand
        private ICommand refreshBorrowCommand;
        public ICommand RefreshBorrowCommand
        {
            get
            {
                if (refreshBorrowCommand == null)
                    refreshBorrowCommand = new CustomCommand(RefreshBorrow);
                return refreshBorrowCommand;
            }
        }

        private async void RefreshBorrow()
        {
            try
            {
                AdminService.Borrow[] borrows;
                Order[] orders;
                using (var asc = new AdminServiceClient())
                {
                    borrows = await asc.GetBorrowsAsync();
                    orders = await asc.GetOrdersAsync();
                }

                var modelBorrow = new ObservableCollection<Model.Borrow>();
                foreach (var b in borrows)
                {
                    modelBorrow.Add(new Model.Borrow()
                        {
                            Deadline = b.Deadline,
                            StartDate = b.StartDate,
                            Id = b.Id,
                            UserId = b.UserId,
                            BrandName = b.BrandName,
                            TypeName = b.TypeName,
                            UserName = b.UserName,
                            StockNumber = b.StockNumber
                        });
                }
                BorrowedTools = modelBorrow;

                var modelOrder = new ObservableCollection<Model.Order>();
                foreach (var o in orders)
                {
                    modelOrder.Add(new Model.Order()
                        {
                            StartDate = o.StartDate,
                            BrandName = o.BrandName,
                            TypeName = o.TypeName,
                            UserName = o.UserName,
                            ToolTypeId = o.ToolTypeId,
                            Id = o.Id
                        });
                }
                OrderedToolTypes = modelOrder;
            }
            catch (Exception e)
            {
                HostIsUnavailable(e.Message);
            }
        }
        #endregion

        #region OrderItemSelectedCommand
        private ICommand orderItemSelectedCommand;
        public ICommand OrderItemSelectedCommand
        {
            get
            {
                if (orderItemSelectedCommand == null)
                    orderItemSelectedCommand = new CustomCommand(OrderItemSelected);
                return orderItemSelectedCommand;
            }
        }

        private void OrderItemSelected()
        {
            try
            {
                var selected = OrderedToolTypes.Where(p => (p.IsChecked == true)).First();

                Tool[] tools;
                using (var asc = new AdminServiceClient())
                {
                    tools = asc.GetAvailableTools(selected.ToolTypeId);
                }

                var newBorrows = new ObservableCollection<Model.Tool>();
                foreach (var t in tools)
                {
                    newBorrows.Add(new Model.Tool()
                        {
                            Id = t.Id,
                            StockNumber = t.StockNumber,
                            ToolTypeId = t.ToolTypeId
                        });
                }
                NewBorrowTools = newBorrows;
            }
            catch (Exception e)
            {
                Debug.WriteLine(e.Message);
                MessageBox.Show("Nincs rendelés kiválasztva!");
            }
        }
        #endregion

        #region BorrowedToolSelectedCommand
        private ICommand borrowedToolSelectedCommand;
        public ICommand BorrowedToolSelectedCommand
        {
            get
            {
                if (borrowedToolSelectedCommand == null)
                    borrowedToolSelectedCommand = new CustomCommand(BorrowedToolSelected);
                return borrowedToolSelectedCommand;
            }
        }

        private void BorrowedToolSelected()
        {
            throw new NotImplementedException();
        }
        #endregion

        #region Constructor
        public ViewModel()
        {
            RefreshBorrow();
            GetToolTypes();
            FinishOperation();
        }
        #endregion

        #region FillDummyData
        private void FillDummyData()
        {
            // Fill Tools Collection
            var toolCollection = new ObservableCollection<Tool>();
            toolCollection.Add(new Tool()
            {
                StockNumber = "M12334",
                ToolTypeId = 1,
                //Type = 
            });

            Tools = toolCollection;
        }
        #endregion

        #region INotifyPropertyChanged interface
        public event PropertyChangedEventHandler PropertyChanged;

        private void PropChanged(string prop)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(prop));
        }
        #endregion

        #region Start & Stop operation
        private void StartOperation()
        {
            CustomCommand.IsEnabled = false;
            StartProgressBar();
        }

        private void FinishOperation()
        {
            CustomCommand.IsEnabled = true;
            StopProgressBar();
        }
        
        private void HostIsUnavailable(string message)
        {
            Debug.WriteLine(message);
            MessageBox.Show("A kért szolgáltatás nem elérhető! Kérjük próbálja meg később!!");
        }
        #endregion

        #region Start & Stop Progress Bar

        private int progressBarValue;
        public int ProgressBarValue
        {
            get
            {
                return progressBarValue;
            }
            set
            {
                progressBarValue = value;
                PropChanged("ProgressBarValue");
            }
        }

        private Timer progressBarTimer;
        private void StartProgressBar()
        {
            progressBarTimer = new Timer();
            progressBarTimer.Elapsed += progressBarTimer_Elapsed;
            progressBarTimer.Interval = 100;
            progressBarTimer.Start();
        }

        void progressBarTimer_Elapsed(object sender, ElapsedEventArgs e)
        {
            var progBar = progressBarValue;
            progBar += 10;
            if (progBar > 100) progBar = 0;
            ProgressBarValue = progBar;
        }

        private void StopProgressBar()
        {
            if (progressBarTimer != null)
                progressBarTimer.Stop();
            ProgressBarValue = 0;
        }
        #endregion
    }
}
